﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace iNet.Media.Imaging
{
	/// <summary>
	/// 以多個 IMetadata 介面為資料來源的影像中繼資料。
	/// </summary>
	public class HybridImageMetadata : HybridMetadata, IImageMetadata
	{
		#region 建構子
		/// <summary>
		/// 初始化新的 HybridImageMetadata 執行個體。
		/// </summary>
		/// <param name="sources">做為資料來源的 IMetadata 介面列表。</param>
		/// <param name="template">範本中繼資料。</param>
		/// <param name="isReadOnly">是否為唯讀。</param>
		/// <param name="updateMode">中繼資料屬性值更新方式，預設值為 PropertyUpdateMode.All。</param>
		public HybridImageMetadata(IList<IMetadata> sources, IMetadata template, bool isReadOnly, PropertyUpdateMode updateMode = PropertyUpdateMode.All)
			: base(sources, template, isReadOnly, updateMode)
		{ }
		#endregion
		#region Aperture
		/// <summary>
		/// 取得或設定光圈值。
		/// </summary>
		public double? Aperture
		{
			get
			{
				return this.GetProperty<double?>((source, userData) =>
				{
					if (source is IImageMetadata)
						return (source as IImageMetadata).Aperture;
					return null;
				});
			}
			set
			{
				this.SetProperty<double?>((target, newValue, userData) =>
				{
					if (target is IImageMetadata)
						(target as IImageMetadata).Aperture = newValue;
					else
						throw new NotSupportedException();
				}, value);
			}
		}
		#endregion
		#region CameraManufacturer
		/// <summary>
		/// 取得或設定相機製造商。
		/// </summary>
		public string CameraManufacturer
		{
			get
			{
				return this.GetProperty<string>((source, userData) =>
				{
					if (source is IImageMetadata)
						return (source as IImageMetadata).CameraManufacturer;
					return null;
				});
			}
			set
			{
				this.SetProperty<string>((target, newValue, userData) =>
				{
					if (target is IImageMetadata)
						(target as IImageMetadata).CameraManufacturer = newValue;
					else
						throw new NotSupportedException();
				}, value);
			}
		}
		#endregion
		#region CameraModel
		/// <summary>
		/// 取得或設定相機型號。
		/// </summary>
		public string CameraModel
		{
			get
			{
				return this.GetProperty<string>((source, userData) =>
				{
					if (source is IImageMetadata)
						return (source as IImageMetadata).CameraModel;
					return null;
				});
			}
			set
			{
				this.SetProperty<string>((target, newValue, userData) =>
				{
					if (target is IImageMetadata)
						(target as IImageMetadata).CameraModel = newValue;
					else
						throw new NotSupportedException();
				}, value);
			}
		}
		#endregion
		#region Clone
		/// <summary>
		/// 建立可修改的 HybridImageMetadata 副本。
		/// </summary>
		/// <returns>HybridImageMetadata 副本。</returns>
		public override object Clone()
		{
			return new HybridImageMetadata(this.Sources, null, false, this.UpdateMode);
		}
		#endregion
		#region ExposureCompensation
		/// <summary>
		/// 取得或設定曝光補償值。
		/// </summary>
		public double? ExposureCompensation
		{
			get
			{
				return this.GetProperty<double?>((source, userData) =>
				{
					if (source is IImageMetadata)
						return (source as IImageMetadata).ExposureCompensation;
					return null;
				});
			}
			set
			{
				this.SetProperty<double?>((target, newValue, userData) =>
				{
					if (target is IImageMetadata)
						(target as IImageMetadata).ExposureCompensation = newValue;
					else
						throw new NotSupportedException();
				}, value);
			}
		}
		#endregion
		#region ExposureProgram
		/// <summary>
		/// 取得或設定曝光程式。
		/// </summary>
		public ExposureProgram? ExposureProgram
		{
			get
			{
				return this.GetProperty<ExposureProgram?>((source, userData) =>
				{
					if (source is IImageMetadata)
						return (source as IImageMetadata).ExposureProgram;
					return null;
				});
			}
			set
			{
				this.SetProperty<ExposureProgram?>((target, newValue, userData) =>
				{
					if (target is IImageMetadata)
						(target as IImageMetadata).ExposureProgram = newValue;
					else
						throw new NotSupportedException();
				}, value);
			}
		}
		#endregion
		#region FlashManufacturer
		/// <summary>
		/// 取得或設定閃光燈製造商。
		/// </summary>
		public string FlashManufacturer
		{
			get
			{
				return this.GetProperty<string>((source, userData) =>
				{
					if (source is IImageMetadata)
						return (source as IImageMetadata).FlashManufacturer;
					return null;
				});
			}
			set
			{
				this.SetProperty<string>((target, newValue, userData) =>
				{
					if (target is IImageMetadata)
						(target as IImageMetadata).FlashManufacturer = newValue;
					else
						throw new NotSupportedException();
				}, value);
			}
		}
		#endregion
		#region FlashModel
		/// <summary>
		/// 取得或設定閃光燈型號。
		/// </summary>
		public string FlashModel
		{
			get
			{
				return this.GetProperty<string>((source, userData) =>
				{
					if (source is IImageMetadata)
						return (source as IImageMetadata).FlashModel;
					return null;
				});
			}
			set
			{
				this.SetProperty<string>((target, newValue, userData) =>
				{
					if (target is IImageMetadata)
						(target as IImageMetadata).FlashModel = newValue;
					else
						throw new NotSupportedException();
				}, value);
			}
		}
		#endregion
		#region FlashState
		/// <summary>
		/// 取得或設定閃光燈狀態。
		/// </summary>
		public FlashState? FlashState
		{
			get
			{
				return this.GetProperty<FlashState?>((source, userData) =>
				{
					if (source is IImageMetadata)
						return (source as IImageMetadata).FlashState;
					return null;
				});
			}
			set
			{
				this.SetProperty<FlashState?>((target, newValue, userData) =>
				{
					if (target is IImageMetadata)
						(target as IImageMetadata).FlashState = newValue;
					else
						throw new NotSupportedException();
				}, value);
			}
		}
		#endregion
		#region FocalLength
		/// <summary>
		/// 取得或設定實際焦距，單位為毫米 (mm)。
		/// </summary>
		public double? FocalLength
		{
			get
			{
				return this.GetProperty<double?>((source, userData) =>
				{
					if (source is IImageMetadata)
						return (source as IImageMetadata).FocalLength;
					return null;
				});
			}
			set
			{
				this.SetProperty<double?>((target, newValue, userData) =>
				{
					if (target is IImageMetadata)
						(target as IImageMetadata).FocalLength = newValue;
					else
						throw new NotSupportedException();
				}, value);
			}
		}
		#endregion
		#region FocalLengthIn35mmFilm
		/// <summary>
		/// 取得或設定等效焦距，單位為毫米 (mm)。
		/// </summary>
		public double? FocalLengthIn35mmFilm
		{
			get
			{
				return this.GetProperty<double?>((source, userData) =>
				{
					if (source is IImageMetadata)
						return (source as IImageMetadata).FocalLengthIn35mmFilm;
					return null;
				});
			}
			set
			{
				this.SetProperty<double?>((target, newValue, userData) =>
				{
					if (target is IImageMetadata)
						(target as IImageMetadata).FocalLengthIn35mmFilm = newValue;
					else
						throw new NotSupportedException();
				}, value);
			}
		}
		#endregion
		#region GeoCoordinate
		/// <summary>
		/// 取得或設定影像的地理座標。
		/// </summary>
		public GeoCoordinate GeoCoordinate
		{
			get
			{
				return this.GetProperty<GeoCoordinate>((source, userData) =>
				{
					if (source is IImageMetadata)
						return (source as IImageMetadata).GeoCoordinate;
					return null;
				});
			}
			set
			{
				this.SetProperty<GeoCoordinate>((target, newValue, userData) =>
				{
					if (target is IImageMetadata)
						(target as IImageMetadata).GeoCoordinate = newValue;
					else
						throw new NotSupportedException();
				}, value);
			}
		}
		#endregion
		#region GetAsReadOnly
		/// <summary>
		/// 取得唯讀中繼資料。
		/// </summary>
		/// <returns>唯讀中繼資料。</returns>
		public override IMetadata GetAsReadOnly()
		{
			if (this.IsReadOnly)
				return this;
			return new HybridImageMetadata(this.Sources, null, true, this.UpdateMode);
		}
		#endregion
		#region ISO
		/// <summary>
		/// 取得或設定 ISO 值。
		/// </summary>
		public int? ISO
		{
			get
			{
				return this.GetProperty<int?>((source, userData) =>
				{
					if (source is IImageMetadata)
						return (source as IImageMetadata).ISO;
					return null;
				});
			}
			set
			{
				this.SetProperty<int?>((target, newValue, userData) =>
				{
					if (target is IImageMetadata)
						(target as IImageMetadata).ISO = newValue;
					else
						throw new NotSupportedException();
				}, value);
			}
		}
		#endregion
		#region LensManufacturer
		/// <summary>
		/// 取得或設定鏡頭製造商。
		/// </summary>
		public string LensManufacturer
		{
			get
			{
				return this.GetProperty<string>((source, userData) =>
				{
					if (source is IImageMetadata)
						return (source as IImageMetadata).LensManufacturer;
					return null;
				});
			}
			set
			{
				this.SetProperty<string>((target, newValue, userData) =>
				{
					if (target is IImageMetadata)
						(target as IImageMetadata).LensManufacturer = newValue;
					else
						throw new NotSupportedException();
				}, value);
			}
		}
		#endregion
		#region LensModel
		/// <summary>
		/// 取得或設定鏡頭型號。
		/// </summary>
		public string LensModel
		{
			get
			{
				return this.GetProperty<string>((source, userData) =>
				{
					if (source is IImageMetadata)
						return (source as IImageMetadata).LensModel;
					return null;
				});
			}
			set
			{
				this.SetProperty<string>((target, newValue, userData) =>
				{
					if (target is IImageMetadata)
						(target as IImageMetadata).LensModel = newValue;
					else
						throw new NotSupportedException();
				}, value);
			}
		}
		#endregion
		#region Orientation
		/// <summary>
		/// 取得或設定影像方向。
		/// </summary>
		public ImageOrientation? Orientation
		{
			get
			{
				return this.GetProperty<ImageOrientation?>((source, userData) =>
				{
					if (source is IImageMetadata)
						return (source as IImageMetadata).Orientation;
					return null;
				});
			}
			set
			{
				this.SetProperty<ImageOrientation?>((target, newValue, userData) =>
				{
					if (target is IImageMetadata)
						(target as IImageMetadata).Orientation = newValue;
					else
						throw new NotSupportedException();
				}, value);
			}
		}
		#endregion
		#region People
		/// <summary>
		/// 取得或設定影像中的人員資訊。
		/// </summary>
		public PersonRegion[] People
		{
			get
			{
				return this.GetProperty<PersonRegion[]>((source, userData) =>
				{
					if (source is IImageMetadata)
						return (source as IImageMetadata).People;
					return null;
				});
			}
			set
			{
				this.SetProperty<PersonRegion[]>((target, newValue, userData) =>
				{
					if (target is IImageMetadata)
						(target as IImageMetadata).People = newValue;
					else
						throw new NotSupportedException();
				}, value);
			}
		}
		#endregion
		#region ShutterSpeed
		/// <summary>
		/// 取得或設定快門速度。
		/// </summary>
		public URational? ShutterSpeed
		{
			get
			{
				return this.GetProperty<URational?>((source, userData) =>
				{
					if (source is IImageMetadata)
						return (source as IImageMetadata).ShutterSpeed;
					return null;
				});
			}
			set
			{
				this.SetProperty<URational?>((target, newValue, userData) =>
				{
					if (target is IImageMetadata)
						(target as IImageMetadata).ShutterSpeed = newValue;
					else
						throw new NotSupportedException();
				}, value);
			}
		}
		#endregion
	}
}
